//
//  VIPAgoraVideoManager.m
//  TTProduct
//
//  Created by Taurin on 2019/12/13.
//  Copyright © 2019 TTProduct. All rights reserved.
//

#import "VIPAgoraVideoManager.h"
#import "VIPAgoraConfig.h"

@interface VIPAgoraVideoManager () <AgoraRtcEngineDelegate>

 @property (nonatomic, strong) VIPRTCAgoraModel *rtcModel;
@property (nonatomic, strong) AgoraRtcEngineKit *agoraKit;

@end

@implementation VIPAgoraVideoManager

#pragma mark - Public

// 进入房间
- (void)joinLiveRoom {
    [VIPWrite writeLogWithFormat:@"%s, token:%@, roomId: %@, uid: %ld", __func__, self.rtcModel.token, self.rtcModel.roomId, self.uid];
   
    // 即将进入教室
    if (self.localWillJoin) { self.localWillJoin(self.uid); }
    
    WS(weakSelf)
    [self.agoraKit joinChannelByToken:self.rtcModel.token channelId:self.rtcModel.roomId info:nil uid:self.uid joinSuccess:^(NSString * _Nonnull channel, NSUInteger uid, NSInteger elapsed) {
        [VIPWrite writeLogWithFormat:@"%s success", __func__];
        
        if (!weakSelf.localDidJoined) { return; }
        // 正在进入教室
        weakSelf.localDidJoined(uid);
    }];
}

#pragma mark AgoraRtcEngine Control

// 退出房间
- (void)quitLiveVideo:(LiveQuitRoom)quitLiveVideoEvent {
    [VIPWrite writeLogWithFormat:@"%s", __func__];
    
    WS(weakSelf)
    [self.agoraKit leaveChannel:^(AgoraChannelStats * _Nonnull stat) {
        [VIPWrite writeLogWithFormat:@"%s success", __func__];
        
        [weakSelf destroyAgoraKit];
        if (!quitLiveVideoEvent) { return; }
        quitLiveVideoEvent();
    }];
}

// 切换视频分辨率(大流/小流)
- (void)setRemoteVideoStream:(NSUInteger)uid type:(VIPVideoStreamType)type {
    [VIPWrite writeLogWithFormat:@"%s, uid: %ld, type: %ld", __func__, uid, (long)type];
    
    [self.agoraKit setRemoteVideoStream:uid type:(AgoraVideoStreamType)type];
}

// 本地视频采集 (打开/ 关闭)
- (void)enableLocalVideoStream:(BOOL)open {
    [VIPWrite writeLogWithFormat:@"%s, open: %d", __func__, open];
    
    [self.agoraKit enableLocalVideo:open];
}

// 本地视频推流 (打开/ 关闭)
- (void)pushLocalVideoStream:(BOOL)muted {
    [VIPWrite writeLogWithFormat:@"%s, muted: %d", __func__, muted];
    
    [self.agoraKit muteLocalVideoStream:muted];
}

// 本地音频推流 (打开/ 关闭)
- (void)pushLocalAudioStream:(BOOL)muted {
    [VIPWrite writeLogWithFormat:@"%s, muted: %d", __func__, muted];
    
    [self.agoraKit muteLocalAudioStream:muted];
}

// 远端视频拉流个人 (打开/ 关闭)
- (void)pullRemoteVideoStream:(NSUInteger)uid muted:(BOOL)muted {
    [VIPWrite writeLogWithFormat:@"%s, uid: %ld, muted: %d", __func__, uid, muted];
    
    [self.agoraKit muteRemoteVideoStream:uid mute:muted];
}

// 远端音频拉流个人 (打开/ 关闭)
- (void)pullRemoteAudioStream:(NSUInteger)uid muted:(BOOL)muted {
    [VIPWrite writeLogWithFormat:@"%s, uid: %ld, muted: %d", __func__, uid, muted];
    
    [self.agoraKit muteRemoteAudioStream:uid mute:muted];
}

// 远端视频拉流全部 (打开/ 关闭)
- (void)pullRemoteVideoStreamAll:(BOOL)muted {
    [VIPWrite writeLogWithFormat:@"%s, muted: %d", __func__, muted];
    
    [self.agoraKit muteAllRemoteVideoStreams:muted];
}

// 远端音频拉流全部 (打开/ 关闭)
- (void)pullRemoteAudioStreamAll:(BOOL)muted {
    [VIPWrite writeLogWithFormat:@"%s, muted: %d", __func__, muted];
    
    [self.agoraKit muteAllRemoteAudioStreams:muted];
}

// 设置美颜效果选项
- (void)setBeautyEffect:(BOOL)isOpen { }

// iPhone
#if TARGET_OS_IPHONE
// 切换前置摄像头, 仅适用于 iOS 平台，不适用于 macOS
- (void)switchCamera {
    [VIPWrite writeLogWithFormat:@"%s", __func__];
    
    [self.agoraKit switchCamera];
}
#endif

// 屏幕共享
// 全屏
- (int)sharedFullScreen {
    [VIPWrite writeLogWithFormat:@"%s", __func__];
    
    return [self sharedScreenWindowId:0];
}

// 指定窗口
- (int)sharedScreenWindowId:(NSUInteger)windowId  {
    [VIPWrite writeLogWithFormat:@"%s, windowId: %lu", __func__, (unsigned long)windowId];
    
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    return [self.agoraKit startScreenCapture:windowId withCaptureFreq:kScreenCaptureFreq bitRate:0 andRect:CGRectZero];
#pragma clang diagnostic pop
}

// 关闭屏幕共享
- (int)stopScreenCapture {
    return [self.agoraKit stopScreenCapture];
}

#pragma mark - Delegate
#pragma mark - AgoraRtcEngineDelegate

// 本地进入频道回调, joinSuccessBlock 优先级高于 didJoinChannel, 2 个同时存在时, didJoinChannel 会被忽略. 需要有 didJoinChannel 回调时, 请将 joinSuccessBlock 设置为 nil.
/*
 - (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine didJoinChannel:(NSString *_Nonnull)channel withUid:(NSUInteger)uid elapsed:(NSInteger)elapsed {
 }
 */

// 本地视频第一帧显示时, 触发此回调
- (void)rtcEngine:(AgoraRtcEngineKit *)engine firstLocalVideoFrameWithSize:(CGSize)size elapsed:(NSInteger)elapsed {
    [VIPWrite writeLogWithFormat:@"%s", __func__];
    
    // 进入教室完成
    if (!self.localFirstVideoDecoded) { return; }
    self.localFirstVideoDecoded(self.uid);
}

// 有时候由于网络原因, 客户端可能会和服务器失去连接, SDK 会进行自动重连, 自动重连成功后触发此回调方法.
- (void)rtcEngine:(AgoraRtcEngineKit *)engine didRejoinChannel:(NSString*)channel withUid:(NSUInteger)uid
          elapsed:(NSInteger) elapsed {
    [VIPWrite writeLogWithFormat:@"%s, uid:%ld", __func__, uid];
    
    // 临时退出教室
    if (!self.localReJoined) { return; }
    self.localReJoined(uid);
}

// 远端进入回调
- (void)rtcEngine:(AgoraRtcEngineKit *)engine didJoinedOfUid:(NSUInteger)uid elapsed:(NSInteger)elapsed {
    [VIPWrite writeLogWithFormat:@"%s, uid:%ld", __func__, uid];

    [self remoteDidJoinedOfUid:uid];
}

- (void)remoteDidJoinedOfUid:(NSUInteger)uid {
    WS(weakSelf)
    [self remoteDidJoined:uid completionHandler:^(NSView * _Nonnull remoteView) {
        [weakSelf setupRemoteVideoUID:uid videoView:remoteView];
        
        if (!weakSelf.remoteDidJoined) { return; }
        weakSelf.remoteDidJoined(uid);
    }];
}

// 远端首帧视频显示回调
- (void)rtcEngine:(AgoraRtcEngineKit *)engine firstRemoteVideoDecodedOfUid:(NSUInteger)uid size:(CGSize)size elapsed:(NSInteger)elapsed {
    [VIPWrite writeLogWithFormat:@"%s, uid:%ld", __func__, uid];
    
    // 远端 视频渲染后 可以在这里处理
    // 只是通知老师 告诉自己进入房间了
    if (!self.remoteFirstVideoDecoded) { return; }
    self.remoteFirstVideoDecoded(uid);
}

// 远端用户停止/重新发送视频回调
- (void)rtcEngine:(AgoraRtcEngineKit *)engine didVideoMuted:(BOOL)muted byUid:(NSUInteger)uid {
    [VIPWrite writeLogWithFormat:@"%s, uid:%ld, muted: %d", __func__, uid, muted];
    
    if (!self.didVideoMuted) return;
    self.didVideoMuted(muted, uid);
}

// 静音回调
- (void)rtcEngine:(AgoraRtcEngineKit * _Nonnull)engine didAudioMuted:(BOOL)muted byUid:(NSUInteger)uid {
    [VIPWrite writeLogWithFormat:@"%s, uid:%ld, muted: %d", __func__, uid, muted];
    
    if (!self.didAudioMuted) return;
    self.didAudioMuted(muted, uid);
}

// 频道内网络质量（上下行）
- (void)rtcEngine:(AgoraRtcEngineKit * _Nonnull)engine
   networkQuality:(NSUInteger)uid
        txQuality:(AgoraNetworkQuality)txQuality
        rxQuality:(AgoraNetworkQuality)rxQuality {
    if (!self.videoNetworkQuality) { return; }
    
    if (txQuality > AgoraNetworkQualityDown ||
        rxQuality > AgoraNetworkQualityDown ||
        rxQuality < 0) { return; }
    
    NSInteger quality = txQuality > rxQuality ? rxQuality : txQuality; // 取最低的
    NSUInteger userID = uid == 0 ? self.uid : uid;
    NSInteger level = [_netWorkLevel[@(quality)] intValue];
    
    self.videoNetworkQuality(userID, level);
}

// 音量提示回调
- (void)rtcEngine:(AgoraRtcEngineKit *)engine reportAudioVolumeIndicationOfSpeakers:(NSArray*)speakers
      totalVolume:(NSInteger)totalVolume {
    if (!self.audioVolumeIndication) { return; }
    
    for (int i = 0; i < speakers.count; i++) {
        AgoraRtcAudioVolumeInfo *volumeInfo = speakers[i];
        // uid 为 0 说明是自己
        NSUInteger uid = volumeInfo.uid;
        if (volumeInfo.uid == 0) {
            uid = self.uid;
        }
        self.audioVolumeIndication(uid, volumeInfo.volume);
    }
}

// 用户离线
- (void)rtcEngine:(AgoraRtcEngineKit *)engine didOfflineOfUid:(NSUInteger)uid reason:(AgoraUserOfflineReason)reason {
    [VIPWrite writeLogWithFormat:@"%s, uid:%ld", __func__, uid];
    
    if (!self.remoteDidOffline) { return; }
    self.remoteDidOffline(uid);
}

// Token 过期已经过期回调
- (void)rtcEngineRequestToken:(AgoraRtcEngineKit *_Nonnull)engine {
    [VIPWrite writeLogWithFormat:@"%s", __func__];
    
    if (!self.tokenDidFailure) return;
     self.tokenDidFailure();
}

// 发生错误回调
- (void)rtcEngine:(AgoraRtcEngineKit *)engine didOccurError:(AgoraErrorCode)errorCode {
    [VIPWrite writeLogWithFormat:@"%s, errorCode: %ld", __func__, (long)errorCode];
}

#pragma mark - Private

- (void)setupLiveServerEngine {
    [VIPWrite writeLogWithFormat:@"%s", __func__];
    // 实例化声网
    [self setupAgoraKit:self.rtcModel.appId];
    
    // 设置日志
    [self setupAgoraLog];
    
    // 设置本地视频属性
    [self setupAgoraVideoConfig];
    
    // 设置本地音频属性
    [self setupAgoraAudioConfig];
    
    // 设置本地视频画布
    [self setupAgoraVideoCanvas];
}

// 进入频道
- (void)joinChannel {
    [VIPWrite writeLogWithFormat:@"%s", __func__];
    [self joinLiveRoom];
}

#pragma mark Setup AgoraKit

// 创建 AgoraRtcEngineKit 实例
- (void)setupAgoraKit:(NSString *_Nonnull)appId {
    [VIPWrite writeLogWithFormat:@"%s appId: %@", __func__, appId];
    _agoraKit = [AgoraRtcEngineKit sharedEngineWithAppId:appId delegate:self];
}

// 设置本地视频属性
- (void)setupAgoraVideoConfig {
    [VIPWrite writeLogWithFormat:@"%s", __func__];
    
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    [self.agoraKit setVideoProfile:kAgoraVideoProfile swapWidthAndHeight: false];
#pragma clang diagnostic pop
    
    // 打开视频模式
    [self.agoraKit enableVideo];
    
    // 监控设备的改变
    [self.agoraKit monitorDeviceChange:YES];
    
    // 开启双流
    [self.agoraKit enableDualStreamMode:YES];
    
    // 远端视频流(大/小)
    [self.agoraKit setRemoteDefaultVideoStreamType:kRemoteDefaultStreamType];
    
    // 小流的属性设置
    [self.agoraKit setParameters:kParametersLowConfig];
    
    // 设置频道模式. 0:通信(默认), 1:直播, 2:游戏(不推荐使用)
    [self.agoraKit setChannelProfile:kAgoraChannelProfile];
    
    // 设置用户角色. 1:主播, 2:观众(默认)
    [self.agoraKit setClientRole:kAgoraClientRole];

    // 本地视图显示模式
    [self.agoraKit setLocalRenderMode:kAgoraVideoRenderMode];
}

// 设置SDK日志
- (void)setupAgoraLog {
    [VIPWrite writeLogWithFormat:@"%s", __func__];
    // 设置日志输出等级
    [self.agoraKit setLogFilter:kAgoraLogFilter];
    [self.agoraKit setLogFile:kAgoraLogPath];
}

// 初始化本地画布
- (void)setupAgoraVideoCanvas {
    [VIPWrite writeLogWithFormat:@"%s, uid:%ld", __func__, self.uid];
    // 设置本地视频显示属性
    AgoraRtcVideoCanvas *videoCanvas = [self setupVideoCanvas:self.uid videoView:self.localView];
    
    [self.agoraKit setupLocalVideo:videoCanvas];
    
    // 开始预览, 必须要在 enableVideo and setupLocalVideo 之后开启
    [self.agoraKit startPreview];
}

// 初始化远端画布
- (void)setupRemoteVideoUID:(NSUInteger)uid videoView:(NSView *)view {
    [VIPWrite writeLogWithFormat:@"%s, uid:%ld", __func__, uid];
    // 设置本地视频显示属性
    AgoraRtcVideoCanvas *videoCanvas = [self setupVideoCanvas:uid videoView:view];
    [self.agoraKit setupRemoteVideo:videoCanvas];
}

- (void)setupAgoraAudioConfig {
    [VIPWrite writeLogWithFormat:@"%s", __func__];
    // 音频采集音量
    [self.agoraKit adjustRecordingSignalVolume:kAgoraAudioRecordingSignalVolume];
    // 设置音频编码配置(音频参数和应用场景)
    [self.agoraKit setAudioProfile:kAgoraAudioProfile scenario:kAgoraAudioScenario];
    // 启用音量提示
     [self.agoraKit enableAudioVolumeIndication:kAgoraAudioVolumeIndication smooth:kAgoraAudioVolumeSmooth report_vad:true];
    // 播放远端音量
    [self.agoraKit adjustPlaybackSignalVolume:kAgoraAudioPlaybackSignalVolume];
}

// 创建 AgoraRtcVideoCanvas 视频画布对象
- (AgoraRtcVideoCanvas *)setupVideoCanvas:(NSUInteger)uid videoView:(NSView *)view {
    [VIPWrite writeLogWithFormat:@"%s, uid:%ld", __func__, uid];
    AgoraRtcVideoCanvas *videoCanvas = [[AgoraRtcVideoCanvas alloc] init];
    videoCanvas.uid = uid;
    videoCanvas.view = view;
    videoCanvas.renderMode = kAgoraVideoRenderMode; // 视图显示模式
    
    return videoCanvas;
}

#pragma mark Setup property

- (VIPRTCAgoraModel *)rtcModel {
    if (!_rtcModel) {
        _rtcModel = (VIPRTCAgoraModel *)self.rtc;
    }
    return _rtcModel;
}

#pragma mark - Destroy AgoraKit

- (void)destroyAgoraKit {
    [VIPWrite writeLogWithFormat:@"%s", __func__];
    [_agoraKit disableVideo]; // 关闭视频模块
    [_agoraKit stopPreview]; // 关闭本地视频预览
    [_agoraKit setupLocalVideo:nil]; // 释放本地视图
    _agoraKit = nil; // 断开引用 AgoraRtcEngineKit 实例
    [AgoraRtcEngineKit destroy]; // 销毁 AgoraRtcEngineKit 实例
    _rtcModel = nil; // 销毁 rct 数据
}

#pragma mark - Instance
static VIPAgoraVideoManager* _instance = nil;
+ (instancetype)shareManager {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[super allocWithZone:NULL] init];
        [VIPWrite writeLogWithFormat:@"%s", __func__];
    });
    return _instance ;
}

+ (id)allocWithZone:(struct _NSZone *)zone {
    return [VIPAgoraVideoManager shareManager];
}

- (id)copyWithZone:(struct _NSZone *)zone {
    return [VIPAgoraVideoManager shareManager];
}

static NSDictionary *_netWorkLevel;
+ (void)load {
    [super load];
    _netWorkLevel = @{@1:@0, @2:@0, @3:@1, @4:@2, @5:@3, @6:@3, @0:@4};
}

@end
